package model.threads;

import java.io.*;
import java.net.*;
import java.nio.ByteBuffer;
import java.util.Calendar;

import view.MainFrame;
import model.environmentConfig.*;

public class Initiator extends Thread {
	private Protocol p;
	private int[] portRange;
	private int port;
	private NodeState nState;
	private InetAddress addr;
	private Socket socket = null;
	private PrintWriter out = null;
	private BufferedReader in = null;
	private String nodeName;
	private boolean endSimulation = false;
	private CommunicationChannel channel = null;
	private long lastComm;
	private int foo;
	public Initiator()
	{
		
	}
	
	public Initiator(Node server, CommunicationChannel cC) //server is the listening node or node to connect to
	{
		super();
		channel = cC;
		this.endSimulation = false;
		this.nodeName = cC.getInitiatorNode().toString();
		this.p = cC.getTransportProtocol();
		this.portRange = cC.getInitiatorPortRange();
		port = portRange[0];
		lastComm=Calendar.getInstance().getTimeInMillis();
		this.nState = server.getNodeState();
		try {
			this.addr = InetAddress.getByName((server.getExternalIPAddress()));
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void run(){
		if(nState != NodeState.RUNNING_NOTHING){
			try{
				client();
			}
			catch(Exception e){
				System.out.println("run()! error");
				e.printStackTrace();
			}
		}
	}
	//timed interval checking
	//check 3 times timeout
	// node state on channel  // channel has key to nodes 
	//  no check needed if running nothing 
	//port range retry for busy/ used port
	//
	// 
	public void client(){
		if(p.getName().equalsIgnoreCase("tcp") || p.getName().equalsIgnoreCase("tcp/ip") ){
			try {
				int nextPort = getNextPort();
				System.out.println(addr);
				System.out.println("port to connect to: "+nextPort);
				socket = new Socket(addr, nextPort);
				System.out.print("Connected!");
				channel.setState(ChannelState.WORKING);
				MainFrame.refresh();
				
				out = new PrintWriter(socket.getOutputStream(), true);
				in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
				while(true){
					foo++;
					out.println("loser!"+foo);
					while (!in.ready()) {}
					System.out.println(in.readLine()); // Read one line and output it
					Thread.sleep(CommunicationChannel.TIME_OUT/4);
				}
			}
			catch (IOException e) {
				// TODO Auto-generated catch block
				if(e instanceof ConnectException){
					channel.setState(ChannelState.NOT_WORKING);
					MainFrame.refresh();
				}
				System.out.println(e.getMessage());
				//System.out.println("Attempting to Connect to !"); // need to figure out how to try the next port
				//client();
				
			}
			catch(InterruptedException e){
				System.out.println("Interuppted!!!!");
			}
		}
		else{//udp here
			byte[] buf = new byte[256];
			int nextPort = getNextPort();
			DatagramPacket d = new DatagramPacket(buf, buf.length, addr, nextPort);
		}
	}
	
	public void end(){
		channel.setState(ChannelState.UNKNOWN);
		MainFrame.refresh();
		
		endSimulation = true;
		try {
			in.close();
			out.close();
			socket.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	public int getNextPort(){
		int val = -1;
		if(port <= portRange[1]){
			val = port;
		}
		else{
			port = portRange[0];
			val = port;
		}
		port++;
		return val;
	}
}
